#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

#include "mongoose.h"
#include "uri_handler.h"
#include "currency.h"


/* dynamic request handlers */

static struct dyn_req_handlers dyn_handlers[] = {
	{ REQ_ADD, "curr", uh_add_currency },
	{ REQ_QUE, "curr", uh_query_currency },
	{ REQ_DEL, "curr", uh_del_currency },
	{ REQ_UNK, NULL, NULL }, /* MUST be the last one */
};

/* HTTP related stuff */

static uri_handler get_uri_handler(int type, const char *uri)
{
	struct dyn_req_handlers *h = dyn_handlers;

	printf("look for dyn handler\n");
	while (h->type != REQ_UNK) {
		if (type == h->type) {
			if (strncmp(uri, h->uri, strlen(h->uri)) == 0)
				return h->handler;
		}
		++h;
	}

	return NULL;
}

/* process all dynamic requests
 * return -1 will cause HTTP 500 code
 */
static int handle_dyn_request(struct mg_connection *conn,
			        const struct mg_request_info *ri,
				const char *uri,
				int req_type,
				int mobile)
{
	uri_handler handler = get_uri_handler(req_type, uri);

	if (!handler)
		return -1;

	return handler(conn, ri, uri, mobile);
}


/*
 * core handler of all requests from client
 * accepted requests are:
 * /m/... for mobile
 * /d/... dynamic requests
 * dynamic requests can be:
 * /d/a/... add records
 * /d/q/... query records
 * /d/r/... remove records
 */
static int http_request_handler(struct mg_connection *conn,
			       	  const struct mg_request_info *ri)
{
#define _is_root(s) (s[0] == 0 || (s[0] == '/' && s[1] == 0))
#define _is_mobile(s) (s[0] == '/' && s[1] == 'm' && (s[2] == '/' || s[2] == 0))
#define _is_dynamic(s) (s[0] == '/' && s[1] == 'd' && s[2] == '/')

#define _is_add_request(s) (s[0] == '/' && s[1] == 'a' && s[2] == '/')
#define _is_query_request(s) (s[0] == '/' && s[1] == 'q' && s[2] == '/')
#define _is_delete_request(s) (s[0] == '/' && s[1] == 'r' && s[2] == '/')

	const char *uri = ri->uri;
	int mobile = 0;

	printf("URI = [%s]\n", uri);

	if (!uri || _is_root(uri)) {
		mg_send_file(conn, "index.html");
		return 0;
	}

	mobile = _is_mobile(uri);	
	if (mobile) {
		uri += (uri[2] == 0) ? 2 : 3;
		if (_is_root(uri)) {
			mg_send_file(conn, "m_index.html");
			return 0;
		}
	}


	if (_is_dynamic(uri)) {
		int type = REQ_UNK;

		printf("dyn req\n");
		uri += 2; /* skip /d */

		if (_is_add_request(uri))
			type = REQ_ADD;
		else if (_is_query_request(uri))
			type = REQ_QUE;
		else if (_is_delete_request(uri))
			type = REQ_DEL;
		
		if (type == REQ_UNK) {
			goto internal_err;
		}

		uri += 3; /* skip request type */
		if (uri[0] == 0) {
			goto internal_err;
		}

		if (handle_dyn_request(conn, ri, uri, type, mobile) == 0)
			return 0;
internal_err:
		send_http_error(conn, 500, "Internal Server Error", "");
	} else {
		/* static files (except index file) are saved in static directory */
		static __thread char file[1024];

		++uri; /* skip / */

		strcpy(file, "static/");
		strncpy(&file[7], uri, 1024 - 7);

		mg_send_file(conn, file);
	}

	return 0;
}


static int callback(enum mg_event event,
		      struct mg_connection *conn,
		      const struct mg_request_info *request_info)
{
	if (event == MG_NEW_REQUEST) {
		return http_request_handler(conn, request_info);
	} else {
		return -1;
	}
}

int main(void)
{
	struct mg_context *ctx;
	const char *options[] = { "listening_ports", "80", NULL };

	printf("starting\n");
	ctx = mg_start(&callback, NULL, options);
	printf("press any key to quit\n");
	getchar();		// Wait until user hits "enter"
	printf("bye!\n");
	mg_stop(ctx);

	return 0;
}
